home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / BumpMapping / BumpUnderwater / BumpUnderWater.cpp next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  14.6 KB  |  421 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Underwater.cpp
  3. //
  4. // Desc: Code to simulate underwater distortion.
  5. //       Games could easily make use of this technique to achieve an underwater
  6. //       effect without affecting geometry by rendering the scene to a texture
  7. //       and applying the bump effect on a rectangle mapped with it.
  8. //
  9. // Note: From the Matrox web site demos
  10. //
  11. // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
  12. //-----------------------------------------------------------------------------
  13. #define STRICT
  14. #include <tchar.h>
  15. #include "D3DX8.h"
  16. #include "D3DApp.h"
  17. #include "D3DFont.h"
  18. #include "D3DUtil.h"
  19. #include "DXUtil.h"
  20. #include "resource.h"
  21.  
  22.  
  23.  
  24.  
  25. //-----------------------------------------------------------------------------
  26. // Function prototypes and global (or static) variables
  27. //-----------------------------------------------------------------------------
  28. inline FLOAT rnd() { return (((FLOAT)rand()-(FLOAT)rand())/(2L*RAND_MAX)); }
  29. inline FLOAT RND() { return (((FLOAT)rand())/RAND_MAX); }
  30. inline DWORD F2DW( FLOAT f ) { return *((DWORD*)&f); }
  31.  
  32. struct BUMPVERTEX
  33. {
  34.     D3DXVECTOR3 p;
  35.     D3DXVECTOR3 n;
  36.     FLOAT       tu1, tv1;
  37.     FLOAT       tu2, tv2;
  38. };
  39.  
  40. #define D3DFVF_BUMPVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2)
  41.  
  42.  
  43.  
  44.  
  45. //-----------------------------------------------------------------------------
  46. // Name: class CMyD3DApplication
  47. // Desc: Application class. The base class (CD3DApplication) provides the 
  48. //       generic functionality needed in all Direct3D samples. CMyD3DApplication 
  49. //       adds functionality specific to this sample program.
  50. //-----------------------------------------------------------------------------
  51. class CMyD3DApplication : public CD3DApplication
  52. {
  53.     CD3DFont*               m_pFont;
  54.     LPDIRECT3DVERTEXBUFFER8 m_pWaterVB;
  55.     LPDIRECT3DTEXTURE8      m_pBumpMap;
  56.     LPDIRECT3DTEXTURE8      m_pBackgroundTexture;
  57.     BOOL                    m_bDeviceValidationFailed;
  58.  
  59.     HRESULT CreateBumpMap();
  60.     HRESULT ConfirmDevice( D3DCAPS8*, DWORD, D3DFORMAT );
  61.  
  62. protected:
  63.     HRESULT OneTimeSceneInit();
  64.     HRESULT InitDeviceObjects();
  65.     HRESULT RestoreDeviceObjects();
  66.     HRESULT InvalidateDeviceObjects();
  67.     HRESULT DeleteDeviceObjects();
  68.     HRESULT Render();
  69.     HRESULT FrameMove();
  70.     HRESULT FinalCleanup();
  71.  
  72. public:
  73.     CMyD3DApplication();
  74. };
  75.  
  76.  
  77.  
  78.  
  79. //-----------------------------------------------------------------------------
  80. // Name: WinMain()
  81. // Desc: Entry point to the program. Initializes everything, and goes into a
  82. //       message-processing loop. Idle time is used to render the scene.
  83. //-----------------------------------------------------------------------------
  84. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  85. {
  86.     CMyD3DApplication d3dApp;
  87.  
  88.     if( FAILED( d3dApp.Create( hInst ) ) )
  89.         return 0;
  90.  
  91.     return d3dApp.Run();
  92. }
  93.  
  94.  
  95.  
  96.  
  97. //-----------------------------------------------------------------------------
  98. // Name: CMyD3DApplication()
  99. // Desc: Application constructor. Sets attributes for the app.
  100. //-----------------------------------------------------------------------------
  101. CMyD3DApplication::CMyD3DApplication()
  102. {
  103.     m_strWindowTitle     = _T("BumpUnderWater: Effect Using BumpMapping");
  104.     m_bUseDepthBuffer    = TRUE;
  105.  
  106.     m_pFont              = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  107.     m_pWaterVB           = NULL;
  108.     m_pBumpMap           = NULL;
  109.     m_pBackgroundTexture = NULL;
  110.     m_bDeviceValidationFailed = FALSE;
  111. }
  112.  
  113.  
  114.  
  115.  
  116. //-----------------------------------------------------------------------------
  117. // Name: OneTimeSceneInit()
  118. // Desc: Called during initial app startup, this function performs all the
  119. //       permanent initialization.
  120. //-----------------------------------------------------------------------------
  121. HRESULT CMyD3DApplication::OneTimeSceneInit()
  122. {
  123.     return S_OK;
  124. }
  125.  
  126.  
  127.  
  128.  
  129. //-----------------------------------------------------------------------------
  130. // Name: FrameMove()
  131. // Desc: Called once per frame, the call is the entry point for animating
  132. //       the scene.
  133. //-----------------------------------------------------------------------------
  134. HRESULT CMyD3DApplication::FrameMove()
  135. {
  136.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_BUMPENVMAT00, F2DW(0.01f) );
  137.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_BUMPENVMAT01, F2DW(0.00f) );
  138.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_BUMPENVMAT10, F2DW(0.00f) );
  139.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_BUMPENVMAT11, F2DW(0.01f) );
  140.  
  141.     BUMPVERTEX* vWaterVertices;
  142.     m_pWaterVB->Lock( 0, 0, (BYTE**)&vWaterVertices, 0 );
  143.     vWaterVertices[0].tu1 =  0.000f; vWaterVertices[0].tv1 = 0.5f*m_fTime + 2.0f;
  144.     vWaterVertices[1].tu1 =  0.000f; vWaterVertices[1].tv1 = 0.5f*m_fTime;
  145.     vWaterVertices[2].tu1 =  1.000f; vWaterVertices[2].tv1 = 0.5f*m_fTime;
  146.     vWaterVertices[3].tu1 =  1.000f; vWaterVertices[3].tv1 = 0.5f*m_fTime + 2.0f;
  147.     m_pWaterVB->Unlock();
  148.  
  149.     return S_OK;
  150. }
  151.  
  152.  
  153.  
  154.  
  155. //-----------------------------------------------------------------------------
  156. // Name: Render()
  157. // Desc: Called once per frame, the call is the entry point for 3d
  158. //       rendering. This function sets up render states, clears the
  159. //       viewport, and renders the scene.
  160. //-----------------------------------------------------------------------------
  161. HRESULT CMyD3DApplication::Render()
  162. {
  163.     // Clear the scene
  164.     m_pd3dDevice->Clear( 0, NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
  165.                          0xff000000, 1.0f, 0L );
  166.  
  167.     // Begin the scene
  168.     if( FAILED( m_pd3dDevice->BeginScene() ) )
  169.         return S_OK;
  170.  
  171.     // Render the waves
  172.     m_pd3dDevice->SetTexture( 0, m_pBumpMap );
  173.     m_pd3dDevice->SetTexture( 1, m_pBackgroundTexture );
  174.  
  175.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  176.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_BUMPENVMAP );
  177.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  178.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_CURRENT );
  179.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
  180.  
  181.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
  182.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_SELECTARG1 );
  183.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  184.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
  185.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
  186.  
  187.     m_pd3dDevice->SetTextureStageState( 2, D3DTSS_COLOROP,   D3DTOP_DISABLE );
  188.     m_pd3dDevice->SetTextureStageState( 2, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
  189.  
  190.     m_pd3dDevice->SetVertexShader( D3DFVF_BUMPVERTEX );
  191.     m_pd3dDevice->SetStreamSource( 0, m_pWaterVB, sizeof(BUMPVERTEX) );
  192.  
  193.     // Verify that the texture operations are possible on the device
  194.     DWORD dwNumPasses;
  195.     if( FAILED( m_pd3dDevice->ValidateDevice( &dwNumPasses ) ) )
  196.     {
  197.         // The right thing to do when device validation fails is to try
  198.         // a different rendering technique.  This sample just warns the user.
  199.         m_bDeviceValidationFailed = TRUE;
  200.     }
  201.  
  202.     m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
  203.  
  204.     // Output statistics
  205.     m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  206.     m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  207.  
  208.     if( m_bDeviceValidationFailed )
  209.     {
  210.         m_pFont->DrawText( 2, 40, D3DCOLOR_ARGB(255,255,0,0), 
  211.             _T("Warning: Device validation failed.  Rendering may not look right.") );
  212.     }
  213.  
  214.     // End the scene.
  215.     m_pd3dDevice->EndScene();
  216.  
  217.     return S_OK;
  218. }
  219.  
  220.  
  221.  
  222.  
  223. //-----------------------------------------------------------------------------
  224. // Name: CreateBumpMapFromSurface()
  225. // Desc: Creates a bumpmap from a surface
  226. //-----------------------------------------------------------------------------
  227. HRESULT CMyD3DApplication::CreateBumpMap()
  228. {
  229.     UINT iWidth  = 256;
  230.     UINT iHeight = 256;
  231.  
  232.     // Create the bumpmap's surface and texture objects
  233.     if( FAILED( m_pd3dDevice->CreateTexture( iWidth, iHeight, 1, 0, 
  234.         D3DFMT_V8U8, D3DPOOL_MANAGED, &m_pBumpMap ) ) )
  235.     {
  236.         return E_FAIL;
  237.     }
  238.  
  239.     // Fill the bumpmap texels to simulate a lens
  240.     D3DLOCKED_RECT lrDst;
  241.     m_pBumpMap->LockRect( 0, &lrDst, 0, 0 );
  242.     DWORD dwDstPitch = (DWORD)lrDst.Pitch;
  243.     BYTE* pDst       = (BYTE*)lrDst.pBits;
  244.  
  245.     for( DWORD y=0; y<iHeight; y++ )
  246.     {
  247.         for( DWORD x=0; x<iWidth; x++ )
  248.         {
  249.             FLOAT fx = x/(FLOAT)iWidth  - 0.5f;
  250.             FLOAT fy = y/(FLOAT)iHeight - 0.5f;
  251.             FLOAT r  = sqrtf( fx*fx + fy*fy );
  252.  
  253.             CHAR iDu = (CHAR)(64*cosf(4.0f*(fx+fy)*D3DX_PI));
  254.             CHAR iDv = (CHAR)(64*sinf(4.0f*(fx+fy)*D3DX_PI));
  255.  
  256.             pDst[2*x+0] = iDu;
  257.             pDst[2*x+1] = iDv;
  258.         }
  259.         pDst += lrDst.Pitch;
  260.     }
  261.  
  262.     m_pBumpMap->UnlockRect(0);
  263.  
  264.     return S_OK;
  265. }
  266.  
  267.  
  268.  
  269.  
  270. //-----------------------------------------------------------------------------
  271. // Name: InitDeviceObjects()
  272. // Desc: Initialize scene objects
  273. //-----------------------------------------------------------------------------
  274. HRESULT CMyD3DApplication::InitDeviceObjects()
  275. {
  276.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  277.  
  278.     if( FAILED( D3DUtil_CreateTexture( m_pd3dDevice, _T("LobbyXPos.bmp"),
  279.                                        &m_pBackgroundTexture, D3DFMT_A8R8G8B8 ) ) )
  280.         return E_FAIL;
  281.  
  282.     // create a bumpmap from info in source surface
  283.     if( FAILED( CreateBumpMap() ) )
  284.         return E_FAIL;
  285.  
  286.     if( FAILED( m_pd3dDevice->CreateVertexBuffer( 4*sizeof(BUMPVERTEX),
  287.                                                   D3DUSAGE_WRITEONLY,
  288.                                                   D3DFVF_BUMPVERTEX,
  289.                                                   D3DPOOL_MANAGED, &m_pWaterVB ) ) )
  290.         return E_FAIL;
  291.  
  292.     BUMPVERTEX* v;
  293.     m_pWaterVB->Lock( 0, 0, (BYTE**)&v, 0 );
  294.     v[0].p = D3DXVECTOR3(-60.0f,-60.0f, 0.0f ); v[0].n = D3DXVECTOR3( 0, 1, 0 );
  295.     v[1].p = D3DXVECTOR3(-60.0f, 60.0f, 0.0f ); v[1].n = D3DXVECTOR3( 0, 1, 0 );
  296.     v[2].p = D3DXVECTOR3( 60.0f,-60.0f, 0.0f ); v[2].n = D3DXVECTOR3( 0, 1, 0 );
  297.     v[3].p = D3DXVECTOR3( 60.0f, 60.0f, 0.0f ); v[3].n = D3DXVECTOR3( 0, 1, 0 );
  298.     v[0].tu2 = 0.000f; v[0].tv2 = 1.0f;
  299.     v[1].tu2 = 0.000f; v[1].tv2 = 0.0f;
  300.     v[2].tu2 = 1.000f; v[2].tv2 = 1.0f;
  301.     v[3].tu2 = 1.000f; v[3].tv2 = 0.0f;
  302.     m_pWaterVB->Unlock();
  303.  
  304.     m_bDeviceValidationFailed = FALSE;
  305.  
  306.     return S_OK;
  307. }
  308.  
  309.  
  310.  
  311.  
  312. //-----------------------------------------------------------------------------
  313. // Name: RestoreDeviceObjects()
  314. // Desc: Initialize scene objects
  315. //-----------------------------------------------------------------------------
  316. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  317. {
  318.     m_pFont->RestoreDeviceObjects();
  319.  
  320.     // Set the transform matrices
  321.     D3DXVECTOR3 vEyePt    = D3DXVECTOR3( 0.0f, 0.0f, -100.0f );
  322.     D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f,    0.0f );
  323.     D3DXVECTOR3 vUpVec    = D3DXVECTOR3( 0.0f, 1.0f,    0.0f );
  324.     D3DXMATRIX matWorld, matView, matProj;
  325.  
  326.     D3DXMatrixIdentity( &matWorld );
  327.     D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
  328.     D3DXMatrixPerspectiveFovLH( &matProj, 1.00f, 1.0f, 1.0f, 3000.0f );
  329.     m_pd3dDevice->SetTransform( D3DTS_WORLD,      &matWorld );
  330.     m_pd3dDevice->SetTransform( D3DTS_VIEW,       &matView );
  331.     m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  332.  
  333.     // Set any appropiate state
  334.     m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,        0xffffffff );
  335.     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE,   TRUE );
  336.     m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
  337.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  338.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  339.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  340.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  341.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  342.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  343.     m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  344.  
  345.     return S_OK;
  346. }
  347.  
  348.  
  349.  
  350.  
  351. //-----------------------------------------------------------------------------
  352. // Name: InvalidateDeviceObjects()
  353. // Desc:
  354. //-----------------------------------------------------------------------------
  355. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  356. {
  357.     m_pFont->InvalidateDeviceObjects();
  358.     return S_OK;
  359. }
  360.  
  361.  
  362.  
  363.  
  364. //-----------------------------------------------------------------------------
  365. // Name: DeleteDeviceObjects()
  366. // Desc: Called when the app is exiting, or the device is being changed,
  367. //       this function deletes any device dependent objects.
  368. //-----------------------------------------------------------------------------
  369. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  370. {
  371.     m_pFont->DeleteDeviceObjects();
  372.     SAFE_RELEASE( m_pWaterVB );
  373.     SAFE_RELEASE( m_pBumpMap );
  374.     SAFE_RELEASE( m_pBackgroundTexture );
  375.  
  376.     return S_OK;
  377. }
  378.  
  379.  
  380.  
  381.  
  382. //-----------------------------------------------------------------------------
  383. // Name: FinalCleanup()
  384. // Desc: Called before the app exits, this function gives the app the chance
  385. //       to cleanup after itself.
  386. //-----------------------------------------------------------------------------
  387. HRESULT CMyD3DApplication::FinalCleanup()
  388. {
  389.     SAFE_DELETE( m_pFont );
  390.     return S_OK;
  391. }
  392.  
  393.  
  394.  
  395.  
  396. //-----------------------------------------------------------------------------
  397. // Name: ConfirmDevice()
  398. // Desc: Called during device intialization, this code checks the device
  399. //       for some minimum set of capabilities
  400. //-----------------------------------------------------------------------------
  401. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  402.                                           D3DFORMAT Format )
  403. {
  404.     // Device must be able to do bumpmapping
  405.     if( 0 == ( pCaps->TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP ) )
  406.         return E_FAIL;
  407.  
  408.     // Accept devices that can create D3DFMT_V8U8 textures
  409.     if( SUCCEEDED( m_pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal,
  410.                                               pCaps->DeviceType, Format,
  411.                                               0, D3DRTYPE_TEXTURE,
  412.                                               D3DFMT_V8U8 ) ) )
  413.         return S_OK;
  414.  
  415.     return E_FAIL;
  416. }
  417.  
  418.  
  419.  
  420.  
  421.